#pragma once

#include <D3D11.h>
#include <Windows.h>
#include <xnamath.h>
#include <D3DX11async.h>

#include <fstream>


namespace TestDX
{

class Shader
{
private:
	__declspec(align(16)) struct MatrixBufferType
	{
		XMMATRIX world;
		XMMATRIX view;
		XMMATRIX projection;
	};

	__declspec(align(16)) struct CameraBufferType
	{
		XMFLOAT3 cameraPosition;
	};

	__declspec(align(16)) struct LightBufferType
	{
		XMFLOAT4 ambientColor;
		XMFLOAT4 diffuseColor;
		XMFLOAT3 direction;
		float specularPower;
		XMFLOAT4 specularColor;
	};


public:
	Shader();
	~Shader();

	bool Init(ID3D11Device *, HWND);
	void Shutdown();
	bool Render(ID3D11DeviceContext *,
				int,
				const XMMATRIX &,
				const XMMATRIX &,
				const XMMATRIX &,
				ID3D11ShaderResourceView *,
				const XMFLOAT3 &,
				const XMFLOAT4 &,
				const XMFLOAT4 &,
				const XMFLOAT3 &,
				const XMFLOAT4 &,
				float);

private:
	// Copy and assign are forbidden
	Shader(const Shader &);
	Shader & operator=(const Shader &);

	bool InitShader(ID3D11Device *, HWND, WCHAR *, WCHAR *);

	void OutputShaderErrorMessage(ID3D10Blob *, HWND, WCHAR *);

	bool SetShaderParameters(ID3D11DeviceContext *,
							 const XMMATRIX &,
							 const XMMATRIX &,
							 const XMMATRIX &,
							 ID3D11ShaderResourceView *,
							 const XMFLOAT3 &,
							 const XMFLOAT4 &,
							 const XMFLOAT4 &,
							 const XMFLOAT3 &,
							 const XMFLOAT4 &,
							 float);

	void RenderShader(ID3D11DeviceContext *, int);

	// Attribs
	ID3D11VertexShader * _pVertexShader;
	ID3D11PixelShader * _pPixelShader;
	ID3D11InputLayout * _pLayout;
	ID3D11SamplerState * _pSamplerState;
	ID3D11Buffer * _pMatrixBuffer;
	ID3D11Buffer * _pCameraBuffer;
	ID3D11Buffer * _pLightBuffer;
};

}